﻿using System;

using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Runtime.InteropServices;

namespace Silvermoon.Controls
{
    public enum GridUnitType : short
    {
        Auto,
        Fixed,
        Dynamic
    }

    [StructLayout(LayoutKind.Explicit)]
    public class GridValue
    {
        [FieldOffset(0)]
        public int IntValue;

        [FieldOffset(0)]
        public float FloatValue;

        [FieldOffset(4)]
        public bool IsFloat;

        public static implicit operator GridValue(int value)
        {
            return new GridValue { IntValue = value };
        }

        public static implicit operator GridValue(float value)
        {
            return new GridValue { FloatValue = value, IsFloat = true };
        }
    }

    /// <summary>
    /// Specifies a unit for a grid row or column.
    /// </summary>
    [StructLayout(LayoutKind.Explicit)]
    public class GridUnit
    {
        /// <summary>
        /// Fixed size row or column.
        /// </summary>
        [FieldOffset(0)]
        internal int fixedValue;

        /// <summary>
        /// Dynamic size row or column. The actual size depends on the grid's size relative to this value.
        /// </summary>
        [FieldOffset(0)]
        internal float dynamicValue;

        /// <summary>
        /// Gets the fixed value.
        /// </summary>
        public int Fixed { get { return fixedValue; } }

        /// <summary>
        /// Gets the dynamic value.
        /// </summary>
        public float Dynamic { get { return dynamicValue; } }

        [FieldOffset(4)]
        internal GridUnitType Type;

        [FieldOffset(8)]
        internal int ActualSize;

        [FieldOffset(12)]
        internal int Offset;

        public int End { get { return Offset + ActualSize; } }


        public static implicit operator GridUnit(int value)
        {
            return new GridUnit { fixedValue = value, Type = GridUnitType.Fixed };
        }

        public static implicit operator GridUnit(float value)
        {
            return new GridUnit { dynamicValue = value, Type = GridUnitType.Dynamic };
        }

        public static implicit operator GridUnit(GridUnitType type)
        {
            if (type != GridUnitType.Auto) throw new NotSupportedException();
            return new GridUnit { Type = type };
        }
    }

    public class AnimationGridUnitCollection : IEnumerable
    {
        private List<GridUnit> list = new List<GridUnit>();

        public void AddRange(params GridUnit[] values)
        {
            list.AddRange(values);
        }

        public void Clear()
        {
            list.Clear();
        }

        public GridUnit this[int index]
        {
            get
            {
                if (index >= list.Count) throw new IndexOutOfRangeException();
                return list[index];
            }
            set
            {
                if (index >= list.Count) throw new IndexOutOfRangeException();
                Validate(value);
                list[index] = value;
            }
        }

        public int Count { get { return list.Count; } }

        private void Validate(object value)
        {
            if (!(value is int) && !(value is float)) throw new InvalidCastException();
        }

        #region IEnumerable Members

        public IEnumerator GetEnumerator()
        {
            return list.GetEnumerator();
        }

        #endregion
    }


}
